﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Shapes;
using Melanchall.DryWetMidi.Core;
using Keyboard = InputManager.Keyboard;
using Timer = System.Threading.Timer;

namespace GenshinLyreBot
{
    public class ActionManager
    {
        public const uint WM_KEYDOWN = 0x0100;
        public const uint WM_KEYUP = 0x0101;
        public const uint WM_SETTEXT = 0x000C;

        private static IntPtr genshinWindow = IntPtr.Zero;

        // C4~B6
        private static Dictionary<int, int> lyreNotes = new Dictionary<int, int> {
            {48,0 }, {50,1}, {52,2}, {53,3}, {55,4}, {57,5}, {59,6},
            {60,7 }, {62,8}, {64,9}, {65,10},{67,11 },{69,12},{71,13},
            {72,14 },{74,15},{76,16},{77,17},{79,18 },{81,19},{83,20},
        };

        private static Dictionary<int, Keys> lyreStrings = new Dictionary<int, Keys>
        {
            {0,Keys.Z }, {1,Keys.X}, {2,Keys.C}, {3,Keys.V}, {4,Keys.B},{5,Keys.N},{6,Keys.M},
            {7,Keys.A }, {8,Keys.S}, {9,Keys.D}, {10,Keys.F}, {11,Keys.G},{12,Keys.H},{13,Keys.J},
            {14,Keys.Q }, {15,Keys.W}, {16,Keys.E}, {17,Keys.R}, {18,Keys.T},{19,Keys.Y},{20,Keys.U},
        };

        private enum ShowWindowEnum
        {
            Hide = 0,
            ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
            Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
            Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
            Restore = 9, ShowDefault = 10, ForceMinimized = 11
        };

        private struct WindowPlacement
        {
            public int length;
            public int flags;
            public int showCmd;
            public Point ptMinPosition;
            public Point ptMaxPosition;
            public Rectangle rcNormalPosition;
            public Rectangle rcDevice;
        }


        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string className, string windowTitle);

        public static IntPtr FindWindow(string lpWindowName)
        {
            return FindWindow(null, lpWindowName);
        }

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

        [DllImport("user32.dll")]
        private static extern int SetForegroundWindow(IntPtr hwnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);

        [DllImport("user32.dll")]
        static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindows);

        [DllImport("user32.dll")]
        private static extern Int32 SendMessage(IntPtr hWnd, UInt32 Msg, char wParam, UInt32 lParam);

        [DllImport("user32.dll")]
        static extern void SwitchToThisWindow(IntPtr hWnd, bool fUnknown);

        public static bool PlayNote(NoteOnEvent note, bool transposeNotes)
        {
            if (!IsWindowFocused("原神")) return false;

            var noteId = (int)note.NoteNumber;
            if (!lyreNotes.ContainsKey(noteId))
            {
                if (transposeNotes)
                {
                    if (noteId < lyreNotes.Keys.First())
                    {
                        noteId = lyreNotes.Keys.First() + noteId % 12;
                    }
                    else if (noteId > lyreNotes.Keys.Last())
                    {
                        noteId = lyreNotes.Keys.Last() - 15 + noteId % 12;
                    }
                }
                else
                {
                    return false;
                }
            }

            PlayNote(noteId, transposeNotes);
            return true;
        }

        public static void PlayNote(int noteId, bool transposeNotes)
        {
            try
            {
                var lyreNote = lyreNotes[noteId];
                var stringKey = lyreStrings[lyreNote];
                KeyTap(stringKey);
            }
            catch
            {
                return;
            }
        }

        public static void KeyTap(Keys key)
        {
            Keyboard.KeyDown(key);
            Keyboard.KeyUp(key);
        }

        public static bool OnSongPlay()
        {
            genshinWindow = FindWindow("原神");
            //BringWindowToFront(genshinWindow);
            SwitchToThisWindow(genshinWindow, true);
            var hWnd = GetForegroundWindow();
            if (genshinWindow.Equals(IntPtr.Zero) || !hWnd.Equals(genshinWindow)) return false;
            return true;
        }

        public static bool IsWindowFocused(IntPtr windowPtr)
        {
            var hWnd = GetForegroundWindow();
            if (windowPtr.Equals(IntPtr.Zero) || !hWnd.Equals(windowPtr)) return false;
            return true;
        }

        public static bool IsWindowFocused(string windowName)
        {
            var windowPtr = FindWindow(windowName);
            return IsWindowFocused(windowPtr);
        }
    }
}
